package iconcurrent.lock;

import iconcurrent.IThreadFactory;

import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author or2
 * @Description 读写锁特性初探 - 非公平时, 新任务如何插队?
 * @create 2021年09月13日 时间: 20:39
 */
public class ReadWriteLock {

    private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(false);
    private static final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
    private static final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();

    public static void main(String[] args) throws InterruptedException {
//        省略try/catch/finally - 读操作
        Callable<Void> read = () -> {
            System.out.println(Thread.currentThread().getName() + " 尝试获取 " + "readLock");
            readLock.lock();
            System.out.println(Thread.currentThread().getName() + " 得+到 " + "readLock");
            Thread.sleep(66);
            readLock.unlock();
            System.out.println(Thread.currentThread().getName() + " 释-放 " + "readLock");
            return null;
        };
//        省略try/catch - 写操作
        Callable<Void> write = () -> {
            System.out.println(Thread.currentThread().getName() + " 尝试获取 " + "writeLock");
            writeLock.lock();
            System.out.println(Thread.currentThread().getName() + " 得+到 " + "writeLock");
            Thread.sleep(88);
            writeLock.unlock();
            System.out.println(Thread.currentThread().getName() + " 释-放 " + "writeLock");
            return null;
        };
//        默认 - 头结点不为'写'可插队 (不可插队?)
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        threadPool.submit(write);
        Thread.sleep(10);
        threadPool.submit(read);
        Thread.sleep(10);
        threadPool.submit(read);
        Thread.sleep(10);
        threadPool.submit(write);
        Thread.sleep(10);
        /*该线程无法插队*/
        threadPool.submit(read);
//        尝试插队 (在第二个读操作和第三个之间)
        ThreadPoolExecutor threadPoolFixed = (ThreadPoolExecutor) Executors.newCachedThreadPool(new IThreadFactory(ReadWriteLock.class));
        for (int i = 0; i < 1000; i++) {
            threadPoolFixed.submit(read);
        }
        threadPoolFixed.shutdown();
    }
}
